using System;
using System.Threading;
using System.Threading.Tasks;
using Me.Prettyprint.Cassandra.Utils;
using CassandraHostConfigurator = Me.Prettyprint.Cassandra.Service.CassandraHostConfigurator;

namespace Me.Prettyprint.Cassandra.Connection
{
    /// <summary>
    /// NodeAutoDiscover is responsible for discovering new nodes that join the ring.
    /// It does it by polling the seed host periodically and getting the ring info.
    /// Once it gets the full list of IP's for the ring, it compares it to the known
    /// hosts.
    /// </summary>
	public class NodeAutoDiscoverService : BackgroundCassandraHostService
	{
		private Logger logger = new Logger(typeof(NodeAutoDiscoverService));
		public const int DEF_AUTO_DISCOVERY_DELAY = 5;
		private NodeDiscovery newNodeSearch;
        private CancellationTokenSource tokenSource = new CancellationTokenSource();
		
		public NodeAutoDiscoverService(HConnectionManager connectionManager, CassandraHostConfigurator cassandraHostConfigurator):base(connectionManager, cassandraHostConfigurator)
		{
			this.retryDelayInSeconds = cassandraHostConfigurator.AutoDiscoveryDelayInSeconds;
			newNodeSearch = new NodeDiscovery(cassandraHostConfigurator, connectionManager);
            var token = tokenSource.Token;
            backgroundTask = Task.Factory.StartNew(() => StartBackgroundProcess(token));
		}
		internal override void Shutdown()
		{
            logger.Info("Shutting down HostTimeoutTracker");
            if (backgroundTask != null)
            {
                tokenSource.Cancel();
            }
            logger.Info("HostTimeTracker shutdown complete.");
        }
		public override void ApplyRetryDelay()
		{
		}
        public void StartBackgroundProcess(CancellationToken token)
        {
            if (token.IsCancellationRequested)
            {
                token.ThrowIfCancellationRequested();
            }
            logger.Info("Staring NodeAutoDiscoveryService " + DateTime.Now.Ticks + " - with delay of " + retryDelayInSeconds + " seconds.");
            while (!token.IsCancellationRequested)
            {
                Thread.Sleep(retryDelayInSeconds * 1000);
                DoAddNodes();
            }
            if (token.IsCancellationRequested)
            {
                token.ThrowIfCancellationRequested();
            }
        }
		public virtual void DoAddNodes()
		{
            newNodeSearch.AddNodes();
		}
	}
}